package top.tangyh.lamp.care.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.tangyh.basic.exception.BizException;
import top.tangyh.lamp.care.entity.BTimePlan;
import top.tangyh.lamp.care.entity.BWorkModules;
import top.tangyh.lamp.care.entity.BWorkRoles;
import top.tangyh.lamp.care.manager.BWorkRolesManager;
import top.tangyh.lamp.care.mapper.BTimePlanMapper;
import top.tangyh.lamp.care.mapper.BWorkModulesMapper;
import top.tangyh.lamp.care.mapper.BWorkPlanMapper;
import top.tangyh.lamp.care.mapper.BWorkRolesMapper;
import top.tangyh.lamp.care.service.BWorkPlanService;
import top.tangyh.basic.base.service.impl.SuperServiceImpl;
import top.tangyh.lamp.care.manager.BWorkPlanManager;
import top.tangyh.lamp.care.entity.BWorkPlan;
import top.tangyh.lamp.care.vo.query.WorkPlanDetailQueryVO;
import top.tangyh.lamp.care.vo.query.WorkPlanQueryVO;
import top.tangyh.lamp.care.vo.result.*;
import top.tangyh.lamp.care.vo.save.BWorkPlanSaveVO;
import top.tangyh.lamp.care.vo.save.WorkPlanInVO;
import top.tangyh.lamp.care.vo.update.BWorkPlanUpdateVO;
import top.tangyh.lamp.care.vo.query.BWorkPlanPageQuery;
import top.tangyh.lamp.common.constant.CommonConstant;
import top.tangyh.lamp.common.utils.IcuDateUtils;
import top.tangyh.lamp.common.utils.PDateUtils;

import java.util.*;
import java.util.stream.Collectors;

import static top.tangyh.lamp.common.constant.CommonConstant.YES_NUMBER;
import static top.tangyh.lamp.common.utils.IcuDateUtils.*;

/**
 * <p>
 * 业务实现类
 * 全局的排班表
 * </p>
 *
 * @author zqb
 * @date 2024-07-18 15:42:26
 * @create [2024-07-18 15:42:26] [zqb] [代码生成器生成]
 */
@Slf4j
@RequiredArgsConstructor
@Service
@Transactional(readOnly = true)
public class BWorkPlanServiceImpl extends SuperServiceImpl<BWorkPlanManager, Long, BWorkPlan> implements BWorkPlanService {

    private final BTimePlanMapper bTimePlanMapper;

    private final BWorkPlanMapper bWorkPlanMapper;

    private final BWorkRolesMapper bWorkRolesMapper;

    private final BWorkModulesMapper bWorkModulesMapper;


    public static final String START_TIME_KEY = "startTimestamp";

    public static final String END_TIME_KEY = "endTimestamp";

    @Override
    public LinkedHashSet<TimePointOutVO> getAllTimePoitByPtAndShift(String moduleId, Long roleId, String patientIdent, String hospitalNumber, Long currTime, Long shiftId) {
        LinkedHashSet<TimePointOutVO> rst = new LinkedHashSet<>();
        if (StrUtil.isBlank(moduleId) || currTime == null || shiftId == null) {
            return rst;
        }
        Long baseDate = DateUtil.beginOfDay(new Date(currTime)).getTime();
        WorkPlanDetailOutVO workPlanDetailOutVO = getShiftTimeSlot(moduleId, hospitalNumber, roleId, baseDate, shiftId);
        if (workPlanDetailOutVO == null) {
            return rst;
        }
        Long startTime = workPlanDetailOutVO.getStartTime();
        Long endTime = workPlanDetailOutVO.getEndTime();
        rst = getAllTimePoitByPt(moduleId, roleId, patientIdent, hospitalNumber, startTime, endTime, currTime);
        return rst;
    }

    @Override
    public LinkedHashSet<TimePointOutVO> getAllTimePoitByPt(String moduleId, Long roleId, String patientIdent, String hospitalNumber, Long startTime, Long endTime, Long currTime) {
        LinkedHashSet<TimePointOutVO> rst = new LinkedHashSet<>();
        if (StrUtil.isBlank(moduleId) || startTime == null || endTime == null) {
            return rst;
        }
        Set<Long> timeBaseAxios = getTimePoitSet(moduleId, roleId, startTime, endTime, currTime);

        //病人自定义时间点
        List<BTimePlan> userTimePointList = new ArrayList<>();
        if (StrUtil.isNotBlank(hospitalNumber)) {
            userTimePointList = bTimePlanMapper.selectListByBusiField(moduleId, patientIdent, hospitalNumber);
        }

        for (BTimePlan o : userTimePointList) {
            if (o == null || o.getTimePoint() == null) {
                continue;
            }
            long time = PDateUtils.getTimestampOfDateTime(o.getTimePoint());
            if (time >= startTime && time <= endTime) {
                TimePointOutVO vo = new TimePointOutVO();
                vo.setTimePoint(time);
                vo.setId(o.getId());
                rst.add(vo);
            }
        }
        //班次时间点
        for (Long time : timeBaseAxios) {
            if (time == null) {
                continue;
            }
            ;
            if (time >= startTime && time <= endTime) {
                TimePointOutVO vo = new TimePointOutVO();
                vo.setTimePoint(time);
                rst.add(vo);
            }
        }
        rst = rst.stream().sorted(Comparator.comparing(TimePointOutVO::getTimePoint)).collect(Collectors.toCollection(LinkedHashSet::new));
        return rst;
    }

    @Override
    public Set<Long> getTimePoitSet(String moduleId, Long roleId, Long startTime, Long endTime, Long currTime) {
        WorkPlanDetailQueryVO queryInVO = new WorkPlanDetailQueryVO();
        queryInVO.setModuleId(moduleId);
        queryInVO.setCurrentDate(DateUtil.beginOfDay(new Date(currTime)).getTime());
        queryInVO.setRoleId(roleId);
        List<WorkPlanDetailOutVO> list = selectWorkPlanDetailListByQuery(queryInVO);
        if (list == null) {
            list = new ArrayList<>();
        }
        List<Long> rstList = new ArrayList<Long>();
        for (WorkPlanDetailOutVO detail : list) {
            if (detail == null || detail.getTimePointList() == null) {
                continue;
            }
            for (TimePointOutVO timePoit : detail.getTimePointList()) {
                if (timePoit == null || timePoit.getTimePoint() == null) {
                    continue;
                }
                rstList.add(timePoit.getTimePoint());
            }
        }
        rstList.stream().filter(o -> o >= startTime && o <= endTime).sorted();
        return new LinkedHashSet<>(rstList);
    }

    @Override
    public Set<Long> getTimePoitSet(String moduleId, Long roleId, Long startTime, Long endTime) {
        WorkPlanDetailQueryVO queryInVO = new WorkPlanDetailQueryVO();
        queryInVO.setModuleId(moduleId);
        queryInVO.setCurrentDate(DateUtil.beginOfDay(new Date(startTime)).getTime());
        queryInVO.setRoleId(roleId);
        List<WorkPlanDetailOutVO> list = selectWorkPlanDetailListByQuery(queryInVO);
        if (list == null) {
            list = new ArrayList<>();
        }
        List<Long> rstList = new ArrayList<Long>();
        for (WorkPlanDetailOutVO detail : list) {
            if (detail == null || detail.getTimePointList() == null) {
                continue;
            }
            for (TimePointOutVO timePoit : detail.getTimePointList()) {
                if (timePoit == null || timePoit.getTimePoint() == null) {
                    continue;
                }
                rstList.add(timePoit.getTimePoint());
            }
        }
        rstList.stream().filter(o -> o >= startTime && o <= endTime).sorted();
        return new LinkedHashSet<>(rstList);
    }

    @Override
    public WorkPlanDetailOutVO getShiftTimeSlot(String moduleId, String hospitalNumber, Long roleId, Long currTime, Long shiftId) {
        WorkPlanDetailQueryVO queryInVO = new WorkPlanDetailQueryVO();
        queryInVO.setModuleId(moduleId);
        queryInVO.setCurrentDate(DateUtil.beginOfDay(new Date(currTime)).getTime());
        queryInVO.setRoleId(roleId);
        queryInVO.setWorkId(shiftId);
        queryInVO.setHospitalNumber(hospitalNumber);
        List<WorkPlanDetailOutVO> list = selectWorkPlanDetailListByQuery(queryInVO);
        if (CollectionUtil.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }


    @Override
    public LinkedHashSet<TimePointOutVO> getAllTimePoitByPt(String moduleId, Long roleId, String patientIdent, String hospitalNumber, Long startTime, Long endTime) {
        LinkedHashSet<TimePointOutVO> rst = new LinkedHashSet<>();
        if (StrUtil.isBlank(moduleId) || startTime == null || endTime == null) {
            return rst;
        }
        Set<Long> timeBaseAxios = getTimePoitSet(moduleId, roleId, startTime, endTime);

        //病人自定义时间点
        List<BTimePlan> userTimePointList = new ArrayList<>();
        if (StrUtil.isNotBlank(hospitalNumber)) {
            userTimePointList = bTimePlanMapper.selectListByBusiField(moduleId, patientIdent, hospitalNumber);
        }

        for (BTimePlan o : userTimePointList) {
            if (o == null || o.getTimePoint() == null) {
                continue;
            }
            long time = PDateUtils.getTimestampOfDateTime(o.getTimePoint());
            if (time >= startTime && time <= endTime) {
                TimePointOutVO vo = new TimePointOutVO();
                vo.setTimePoint(time);
                vo.setId(o.getId());
                rst.add(vo);
            }
        }
        //班次时间点
        for (Long time : timeBaseAxios) {
            if (time == null) {
                continue;
            }
            ;
            if (time >= startTime && time <= endTime) {
                TimePointOutVO vo = new TimePointOutVO();
                vo.setTimePoint(time);
                rst.add(vo);
            }
        }
        rst = rst.stream().sorted(Comparator.comparing(TimePointOutVO::getTimePoint)).collect(Collectors.toCollection(LinkedHashSet::new));
        return rst;

    }

    @Override
    public List<WorkPlanDetailOutVO> selectWorkPlanDetailListByQuery(WorkPlanDetailQueryVO queryVO) {
        Long roleId = queryVO.getRoleId();
        Long currentDate = queryVO.getCurrentDate();
        String moduleId = queryVO.getModuleId();
        //根据角色、模块id、具体班次id，查找所有的排班
        List<WorkPlanOutVO> workPlanOutVOList = bWorkPlanMapper.selectListWorkPlanByQuery("", queryVO.getModuleId(), roleId, queryVO.getWorkId(), YES_NUMBER);

        //根据每个班次的起始时间范围 查找病人的时间点集合 模块id
        List<WorkPlanDetailOutVO> list = new ArrayList<>();

        Long finalCurrentDate = currentDate;
        workPlanOutVOList.forEach(yxWorkPlanVo -> {
            //获取每个班次起始时间
            String startTime = yxWorkPlanVo.getStartTime();
            String endTime = yxWorkPlanVo.getEndTime();
            int startHour = getHour(startTime);
            int startMinute = getMinute(startTime);
            int endHour = getHour(endTime);
            int endMinute = getMinute(endTime);
            //根据传入的天 时间戳计算当天的开始和结束的时间戳
            Map<String, Long> timeMap = getStartEndTimestampByTimeStr(finalCurrentDate, startTime, endTime, yxWorkPlanVo.getAddDay());
            long startTimestamp = timeMap.get(START_TIME_KEY);
            long endTimestamp = timeMap.get(END_TIME_KEY);
            DateTime startDate = DateUtil.date(startTimestamp);
            String startTimeStr = DateUtil.formatDateTime(startDate);
            DateTime endDate = DateUtil.date(endTimestamp);
            String endTimeStr = DateUtil.formatDateTime(endDate);
            //根据每个班次时间范围查找病人的时间点集合
            log.debug("班次={} startTimestamp={} endTimestamp={} startStr={} endStr={}", yxWorkPlanVo.getWorkName(), startTimestamp, endTimestamp, startTimeStr, endTimeStr);
            List<BTimePlan> patTimePlanList = bTimePlanMapper.selectListByRangeAndModuleId(startTimeStr, endTimeStr, Collections.singletonList(moduleId), queryVO.getHospitalNumber());
            //获取班次的时间范围的时间点
            Integer interval = yxWorkPlanVo.getInterval();
            int totalMinutes = IcuDateUtils.getTotalMinutesByHourMinute(startHour, startMinute, endHour, endMinute);
            int counts = IcuDateUtils.getIntervalCounts(totalMinutes, interval);
            Set<Long> workAllTimePoints = IcuDateUtils.getAllTimePointsByTimeRange(startTimestamp, endTimestamp, counts, interval, queryVO.getModuleId());
            //病人的时间点加入结果集中
            List<TimePointOutVO> patTimePointVOList = patTimePlanList.stream().map(TimePointOutVO::new).collect(Collectors.toList());
            List<TimePointOutVO> allTimePoints = new ArrayList<>();

            if (null == queryVO.getRkTime()) {
                workAllTimePoints.forEach(timePoint -> {
                    allTimePoints.add(new TimePointOutVO(timePoint));
                });

                patTimePointVOList.forEach(timePointOutVO -> {
                    if (!workAllTimePoints.contains(timePointOutVO.getTimePoint())) {
                        allTimePoints.add(timePointOutVO);
                    }
                });
            } else {
                //排班的所有时间点都加入结果集中
                workAllTimePoints.forEach(timePoint -> {
                    if (null != queryVO.getRkTime()) {
                        if (queryVO.getRkTime() >= startTimestamp && queryVO.getRkTime() <= endTimestamp) {
                            if (queryVO.getRkTime() < timePoint) {
                                allTimePoints.add(new TimePointOutVO(timePoint));
                            }
                        } else if (queryVO.getRkTime() < startTimestamp) {
                            allTimePoints.add(new TimePointOutVO(timePoint));
                        }
                    } else {
                        allTimePoints.add(new TimePointOutVO(timePoint));
                    }
                });

                if (null != queryVO.getRkTime() && queryVO.getRkTime() >= startTimestamp && queryVO.getRkTime() <= endTimestamp) {
                    allTimePoints.add(new TimePointOutVO(queryVO.getRkTime()));
                }

                patTimePointVOList.forEach(timePointOutVO -> {
                    if (!workAllTimePoints.contains(timePointOutVO.getTimePoint())) {
                        allTimePoints.add(timePointOutVO);
                    }
                });
            }


            //按时间升序排序
            List<TimePointOutVO> timePointList = allTimePoints.stream().sorted(Comparator.comparing(TimePointOutVO::getTimePoint)).collect(Collectors.toList());
            WorkPlanDetailOutVO workPlanDetailOutVO = new WorkPlanDetailOutVO();
            workPlanDetailOutVO.setId(yxWorkPlanVo.getId());
            workPlanDetailOutVO.setStartTime(startTimestamp);
            workPlanDetailOutVO.setEndTime(endTimestamp);
            workPlanDetailOutVO.setSort(yxWorkPlanVo.getSort());
            workPlanDetailOutVO.setWorkName(yxWorkPlanVo.getWorkName());
            workPlanDetailOutVO.setTimePointList(timePointList);
            workPlanDetailOutVO.setAddDay(yxWorkPlanVo.getAddDay());
            list.add(workPlanDetailOutVO);
        });

        if (null != queryVO.getRkTime()) {
            for (int i = 0; i < list.size(); i++) {
                WorkPlanDetailOutVO workPlanDetailOutVO = list.get(i);
                if (workPlanDetailOutVO.getEndTime() < queryVO.getRkTime()) {
                    list.remove(i);
                    i--;
                }
            }
        }
        //按照班次开始时间排序班次
        List<WorkPlanDetailOutVO> result = list.stream().sorted(Comparator.comparing(WorkPlanDetailOutVO::getSort)).collect(Collectors.toList());

        return result;
    }

    public Map<String, Long> getStartEndTimestampByTimeStr(long currentDay, String startTimeStr, String endTimeStr, Integer addday) {
        int startHour = getHour(startTimeStr);
        int startMinute = getMinute(startTimeStr);
        int endHour = getHour(endTimeStr);
        int endMinute = getMinute(endTimeStr);
        long startTimestamp = IcuDateUtils.getTimestampByHourMinute(currentDay, addday != null ? addday : 0, startHour, startMinute);
        long endTimestamp = IcuDateUtils.getTimestampByHourMinute(currentDay, addday != null ? addday : 0, endHour, endMinute);
        //结束时间小于开始时间，结束时间戳计算需要+1
        if (startHour > endHour) {
            endTimestamp = IcuDateUtils.getTimestampByHourMinute(currentDay, addday != null ? addday + 1 : 1, endHour, endMinute);
        }
        Map<String, Long> timeMap = new HashMap<>();
        timeMap.put(START_TIME_KEY, startTimestamp);
        timeMap.put(END_TIME_KEY, endTimestamp);
        return timeMap;
    }


    @Override
    public PageOutputDTO<WorkPlanOutVO> selectPageByQuery(WorkPlanQueryVO queryVO) {

        List<WorkPlanOutVO> workPlanOutVOList = bWorkPlanMapper.selectPageListByQuery(queryVO.getWorkName(), queryVO.getModuleId(), queryVO.getRoleId(), null, queryVO.getEnabled(), (queryVO.getPage() - 1) * queryVO.getSize(), queryVO.getSize());
        Set<Long> workIdSet = workPlanOutVOList.stream().map(WorkPlanOutVO::getId).collect(Collectors.toSet());
        //根据workId集合查询关联的角色和模块，需要返回给前端
        Map<Long, List<BWorkRoles>> roleMap = bWorkRolesMapper.selectListByWorkIds(workIdSet).stream().collect(Collectors.groupingBy(BWorkRoles::getWorkId));
        Map<Long, List<BWorkModules>> moduleMap = bWorkModulesMapper.selectListByWorkIds(workIdSet).stream().collect(Collectors.groupingBy(BWorkModules::getWorkId));


        workPlanOutVOList = workPlanOutVOList.stream().peek(workPlanOutVO -> {
            Long workId = workPlanOutVO.getId();
            if (roleMap.containsKey(workId)) {
                List<Long> roleIds = roleMap.get(workId).stream().map(BWorkRoles::getRoleId).collect(Collectors.toList());
                workPlanOutVO.setRoleIdList(roleIds);
            }
            if (moduleMap.containsKey(workId)) {
                List<String> moduleIds = moduleMap.get(workId).stream().map(BWorkModules::getModuleId).collect(Collectors.toList());
                workPlanOutVO.setModuleIdList(moduleIds);
            }
            if (queryVO.getCurrentDate() != null) {
                Map<String, Long> timeMap = getStartEndTimestampByTimeStr(queryVO.getCurrentDate(), workPlanOutVO.getStartTime(), workPlanOutVO.getEndTime(), workPlanOutVO.getAddDay());
                Long startTime = timeMap.get(START_TIME_KEY);
                Long endTime = timeMap.get(END_TIME_KEY);
                workPlanOutVO.setStartTimestamp(startTime);
                workPlanOutVO.setEndTimestamp(endTime);
                List<Long> timePoints = getTimePointsByStartEndTimestamp(startTime, endTime, workPlanOutVO.getInterval(), queryVO.getModuleId());
                workPlanOutVO.setTimePoints(timePoints);
            }
        }).sorted(Comparator.comparing(WorkPlanOutVO::getSort)).collect(Collectors.toList());
        Long total = bWorkPlanMapper.selectTotalCount(queryVO.getWorkName(), queryVO.getModuleId(), queryVO.getRoleId(), null, queryVO.getEnabled());
        Long pages = (total + queryVO.getSize() - 1) / queryVO.getSize();
        if (null != queryVO.getRkTime()) {
            for (int i = 0; i < workPlanOutVOList.size(); i++) {
                WorkPlanOutVO workPlanOutVO = workPlanOutVOList.get(i);
                if (workPlanOutVO.getEndTimestamp() < queryVO.getRkTime()) {
                    workPlanOutVOList.remove(i);
                    i--;
                }
            }
        }
        return new PageOutputDTO<>(total, pages, queryVO.getPage().longValue(), workPlanOutVOList);
    }

    /**
     * 根据开始和结束时间戳计算时间点
     *
     * @param startTimestamp
     * @param endTimestamp
     * @param interval
     * @return
     */
    public List<Long> getTimePointsByStartEndTimestamp(Long startTimestamp, Long endTimestamp, int interval, String moduleId) {
        int totalMinutes = IcuDateUtils.getTotalMinutesByStartEndTimestamp(startTimestamp, endTimestamp);
        int counts = IcuDateUtils.getIntervalCounts(totalMinutes, interval);
        Set<Long> timePointsSet = IcuDateUtils.getAllTimePointsByTimeRange(startTimestamp, endTimestamp, counts, interval, moduleId);
        List<Long> timePoints = timePointsSet.stream().sorted(Comparator.comparing(Long::longValue)).collect(Collectors.toList());
        return timePoints;
    }


    @Override
    public List<WorkPlanDetailOutVO> selectDetailListByQuery(WorkPlanDetailQueryVO queryVO) {
        Long roleId = queryVO.getRoleId();
        Long currentDate = queryVO.getCurrentDate();
        String moduleId = queryVO.getModuleId();
        //根据角色、模块id、具体班次id，查找所有的排班
        List<WorkPlanOutVO> workPlanOutVOList = bWorkPlanMapper.selectListWorkPlanByQuery("", queryVO.getModuleId(), roleId, queryVO.getWorkId(), YES_NUMBER);

        List<WorkPlanDetailOutVO> list = new ArrayList<>();

        Long finalCurrentDate = currentDate;
        workPlanOutVOList.forEach(yxWorkPlanVo -> {
            //获取每个班次起始时间
            String startTime = yxWorkPlanVo.getStartTime();
            String endTime = yxWorkPlanVo.getEndTime();
            int startHour = getHour(startTime);
            int startMinute = getMinute(startTime);
            int endHour = getHour(endTime);
            int endMinute = getMinute(endTime);
            //根据传入的天 时间戳计算当天的开始和结束的时间戳
            Map<String, Long> timeMap = getStartEndTimestampByTimeStr(finalCurrentDate, startTime, endTime, yxWorkPlanVo.getAddDay());
            long startTimestamp = timeMap.get(START_TIME_KEY);
            long endTimestamp = timeMap.get(END_TIME_KEY);
            DateTime startDate = DateUtil.date(startTimestamp);
            String startTimeStr = DateUtil.formatDateTime(startDate);
            DateTime endDate = DateUtil.date(endTimestamp);
            String endTimeStr = DateUtil.formatDateTime(endDate);
            //根据每个班次时间范围查找病人的时间点集合
            log.debug("班次={} startTimestamp={} endTimestamp={} startStr={} endStr={}", yxWorkPlanVo.getWorkName(), startTimestamp, endTimestamp, startTimeStr, endTimeStr);
            List<BTimePlan> patTimePlanList = bTimePlanMapper.selectListByRangeAndModuleId(startTimeStr, endTimeStr, Collections.singletonList(moduleId), queryVO.getHospitalNumber());
            //获取班次的时间范围的时间点
            Integer interval = yxWorkPlanVo.getInterval();
            int totalMinutes = IcuDateUtils.getTotalMinutesByHourMinute(startHour, startMinute, endHour, endMinute);
            int counts = IcuDateUtils.getIntervalCounts(totalMinutes, interval);
            Set<Long> workAllTimePoints = IcuDateUtils.getAllTimePointsByTimeRange(startTimestamp, endTimestamp, counts, interval, queryVO.getModuleId());
            //病人的时间点加入结果集中
            List<TimePointOutVO> patTimePointVOList = patTimePlanList.stream().map(TimePointOutVO::new).collect(Collectors.toList());
            List<TimePointOutVO> allTimePoints = new ArrayList<>();

            if (null == queryVO.getRkTime()) {
                workAllTimePoints.forEach(timePoint -> {
                    allTimePoints.add(new TimePointOutVO(timePoint));
                });

                patTimePointVOList.forEach(timePointOutVO -> {
                    if (!workAllTimePoints.contains(timePointOutVO.getTimePoint())) {
                        allTimePoints.add(timePointOutVO);
                    }
                });
            } else {
                //排班的所有时间点都加入结果集中
                workAllTimePoints.forEach(timePoint -> {
                    if (null != queryVO.getRkTime()) {
                        if (queryVO.getRkTime() >= startTimestamp && queryVO.getRkTime() <= endTimestamp) {
                            if (queryVO.getRkTime() < timePoint) {
                                allTimePoints.add(new TimePointOutVO(timePoint));
                            }
                        } else if (queryVO.getRkTime() < startTimestamp) {
                            allTimePoints.add(new TimePointOutVO(timePoint));
                        }
                    } else {
                        allTimePoints.add(new TimePointOutVO(timePoint));
                    }
                });

                if (null != queryVO.getRkTime() && queryVO.getRkTime() >= startTimestamp && queryVO.getRkTime() <= endTimestamp) {
                    allTimePoints.add(new TimePointOutVO(queryVO.getRkTime()));
                }

                patTimePointVOList.forEach(timePointOutVO -> {
                    if (!workAllTimePoints.contains(timePointOutVO.getTimePoint())) {
                        allTimePoints.add(timePointOutVO);
                    }
                });
            }


            //按时间升序排序
            List<TimePointOutVO> timePointList = allTimePoints.stream().sorted(Comparator.comparing(TimePointOutVO::getTimePoint)).collect(Collectors.toList());
            WorkPlanDetailOutVO workPlanDetailOutVO = new WorkPlanDetailOutVO();
            workPlanDetailOutVO.setId(yxWorkPlanVo.getId());
            workPlanDetailOutVO.setStartTime(startTimestamp);
            workPlanDetailOutVO.setEndTime(endTimestamp);
            workPlanDetailOutVO.setSort(yxWorkPlanVo.getSort());
            workPlanDetailOutVO.setWorkName(yxWorkPlanVo.getWorkName());
            workPlanDetailOutVO.setTimePointList(timePointList);
            workPlanDetailOutVO.setAddDay(yxWorkPlanVo.getAddDay());
            list.add(workPlanDetailOutVO);
        });

        if (null != queryVO.getRkTime()) {
            for (int i = 0; i < list.size(); i++) {
                WorkPlanDetailOutVO workPlanDetailOutVO = list.get(i);
                if (workPlanDetailOutVO.getEndTime() < queryVO.getRkTime()) {
                    list.remove(i);
                    i--;
                }
            }
        }
        //按照班次开始时间排序班次
        List<WorkPlanDetailOutVO> result = list.stream().sorted(Comparator.comparing(WorkPlanDetailOutVO::getSort)).collect(Collectors.toList());

        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(WorkPlanInVO inVO) {
        String workName = inVO.getWorkName();
        BWorkPlan yxWorkPlanPO = bWorkPlanMapper.selectOneByName(workName);
        if (yxWorkPlanPO != null) {
            throw new BizException("排班计划名称重复");
        }
        String startTime = inVO.getStartTime();
        String endTime = inVO.getEndTime();
        int startHour = getHour(startTime);
        int startMinute = getMinute(startTime);

        int endHour = getHour(endTime);
        int endMinute = getMinute(endTime);
        //限制间隔大小
        checkInterval(startHour, startMinute, endHour, endMinute, inVO.getInterval());

        BWorkPlan workPlanPO = new BWorkPlan();
        workPlanPO.setAddDay(inVO.getAddDay());
        BeanUtil.copyProperties(inVO, workPlanPO);
        bWorkPlanMapper.insert(workPlanPO);
        //添加关联的角色
        Long workId = workPlanPO.getId();
        List<Long> roleIdList = inVO.getRoleIdList();
        if (CollectionUtil.isNotEmpty(roleIdList)) {
            roleIdList.forEach(roleId -> {
                bWorkRolesMapper.insert(new BWorkRoles(roleId, workId));
            });
        }
        //添加关联的模块
        List<String> moduleIdList = inVO.getModuleIdList();
        if (CollectionUtil.isNotEmpty(moduleIdList)) {
            moduleIdList.forEach(moduleId -> {
                bWorkModulesMapper.insert(new BWorkModules(workId, moduleId));
            });
        }

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(WorkPlanInVO inVO) {
        Long workId = inVO.getId();
        BWorkPlan workPlanPO = bWorkPlanMapper.selectById(workId);
        if (!StrUtil.equals(workPlanPO.getWorkName(), inVO.getWorkName())) {
            BWorkPlan yxWorkPlanPO = bWorkPlanMapper.selectOneByName(inVO.getWorkName());
            if (yxWorkPlanPO != null) {
                throw new BizException("排班计划名称重复");
            }
        }
        //限制间隔大小
        int startHour = getHour(inVO.getStartTime());
        int startMinute = getMinute(inVO.getStartTime());

        int endHour = getHour(inVO.getEndTime());
        int endMinute = getMinute(inVO.getEndTime());
        checkInterval(startHour, startMinute, endHour, endMinute, inVO.getInterval());

        BeanUtil.copyProperties(inVO, workPlanPO);
        bWorkPlanMapper.updateById(workPlanPO);
        //删除老的关联关系
        bWorkRolesMapper.deleteByWorkId(workId);
        bWorkModulesMapper.deleteByWorkId(workId);
        List<Long> roleIdList = inVO.getRoleIdList();
        if (CollectionUtil.isNotEmpty(roleIdList)) {
            roleIdList.forEach(roleId -> bWorkRolesMapper.insert(new BWorkRoles(roleId, workId)));
        }
        List<String> moduleIdList = inVO.getModuleIdList();
        if (CollectionUtil.isNotEmpty(moduleIdList)) {
            moduleIdList.forEach(moduleId -> bWorkModulesMapper.insert(new BWorkModules(workId, moduleId)));
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(List<Long> ids) {
        ids.forEach(id -> {
            BWorkPlan workPlanPO = bWorkPlanMapper.selectById(id);
            if (workPlanPO != null) {
                BWorkPlan update = new BWorkPlan();
                update.setId(id);
                update.setIsDeleted(YES_NUMBER);
                bWorkPlanMapper.updateById(update);
                bWorkRolesMapper.deleteByWorkId(id);
                bWorkRolesMapper.deleteByWorkId(id);
            }
        });

    }


    @Override
    public Set<Long> getTimePoitSetByShift(String moduleId,  String hospitalNumber, Long roleId, Long currTime, Long shiftId) {
        WorkPlanDetailOutVO workPlanDetailOutVO = getShiftTimeSlot(moduleId, hospitalNumber, roleId, currTime, shiftId);
        if (workPlanDetailOutVO == null) {
            return new LinkedHashSet<>();
        }
        return workPlanDetailOutVO.getTimePointList().stream().map(TimePointOutVO::getTimePoint).collect(Collectors.toCollection(LinkedHashSet::new));
    }

    @Override
    public LinkedHashSet<Long> getAllTimePoit(Long currDate, String moduleId) {
        LinkedHashSet<Long> rst = new LinkedHashSet<>();
        WorkPlanDetailQueryVO workPlanDetailQueryVO = new WorkPlanDetailQueryVO();
        workPlanDetailQueryVO.setCurrentDate(DateUtil.beginOfDay(new Date(currDate)).getTime());
        workPlanDetailQueryVO.setModuleId(moduleId);
        List<WorkPlanDetailOutVO> list = selectDetailListByQuery(workPlanDetailQueryVO);
        for (WorkPlanDetailOutVO detail : list) {
            if (detail == null || CollectionUtil.isEmpty(detail.getTimePointList())) {
                continue;
            }
            for (TimePointOutVO point : detail.getTimePointList()) {
                if (point == null || point.getTimePoint() == null) {
                    continue;
                }
                rst.add(point.getTimePoint());
            }

        }
        rst.stream().sorted();
        return rst;
    }




}


